/*
 * $Id$
 */
package py.windmill.util;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;

/**
 *
 * @author myang
 */
public class Query {

    private DataSource _ds;
    private String _sql;

    /**
     * 
     * @param ds
     * @param sql 
     */
    public Query(final DataSource ds, final String sql) {
        _ds = ds;
        _sql = sql;
    }

    /**
     * 
     * @param <T>
     * @param m
     * @param args
     * @return 
     */
    public <T> T first(final RowMapper<T> m, final Object... args) {
        final QueryRunner qr = new QueryRunner(_ds);
        try {
            return qr.query(_sql, new ResultSetHandler<T>() {

                @Override
                public T handle(final ResultSet rs) throws SQLException {
                    if (rs.next()) {
                        try {
                            return m.mapRow(rs);
                        }
                        catch (Exception ex) {
                            throw new RuntimeException(ex);
                        }
                    }
                    return null;
                }
            }, args);
        }
        catch (SQLException ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * 
     * @param <T>
     * @param m
     * @param args
     * @return 
     */
    public <T> List<T> list(final RowMapper<T> m, final Object... args) {
        final QueryRunner qr = new QueryRunner(_ds);
        try {
            return qr.query(_sql, new ResultSetHandler<List<T>>() {
                private List<T> rt = new ArrayList<T>();

                @Override
                public List<T> handle(final ResultSet rs) throws SQLException {
                    while (rs.next()) {
                        try { 
                            rt.add(m.mapRow(rs));
                        }
                        catch (Exception ex) {
                            throw new RuntimeException(ex);
                        }
                    }
                    return rt;
                }
            }, args);
        }
        catch (SQLException ex) {
            throw new RuntimeException(ex);
        }
    }
}
